package net.gldwork.facadegen.apt;

import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import net.gldwork.facadegen.annotations.Facade;
import net.gldwork.facadegen.util.FacadeGenUtil;
import net.gldwork.facadegen.util.SPUtil;
import net.gldwork.srcpdr.SourceProducer;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Filer;
import com.sun.mirror.apt.Messager;
import com.sun.mirror.declaration.ClassDeclaration;
import com.sun.mirror.declaration.PackageDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;

public class FacadeGenAP implements AnnotationProcessor {

	private AnnotationProcessorEnvironment env;
	public static Set<String> handledTypes = new HashSet<String>();

	public static final String[] JAR_SCAN_PKGS = { "com.linkage.richers.bo" };

	public FacadeGenAP(AnnotationProcessorEnvironment env) {
		this.env = env;

	}

	@Override
	public void process() {

		Messager messager = env.getMessager();
		try {

			for (TypeDeclaration typeD : env.getSpecifiedTypeDeclarations()) {
				Facade facade = FacadeGenUtil.findFacade(typeD);
				String qname = typeD.getQualifiedName();
				if (facade != null) {

					handledTypes.add(qname);

				} else {

					handledTypes.remove(qname);

				}

			}

			if (JAR_SCAN_PKGS != null && JAR_SCAN_PKGS.length > 0) {
				for (String pkg : JAR_SCAN_PKGS) {
					PackageDeclaration packageD = env.getPackage(pkg);
					for (ClassDeclaration classD : packageD.getClasses()) {
						if (!handledTypes.contains(classD.getQualifiedName())) {
							handledTypes.add(classD.getQualifiedName());

						}

					}
				}
			}

			SourceProducer sp = SPUtil.initSourceProducer();
			for (Iterator<String> it = handledTypes.iterator(); it.hasNext();) {
				String qname = it.next();
				TypeDeclaration typeD = env.getTypeDeclaration(qname);
				Facade facade = FacadeGenUtil.findFacade(typeD);
				if (facade == null) {
					it.remove();
					continue;
				} else {
					FacadeGenUtil.handleTypeD(typeD, sp);

				}

			}
			if (sp.getName() != null) {
				Filer f = env.getFiler();

				PrintWriter pw = f.createSourceFile(sp.getQualifiedName());
				pw.print(sp.toString());

				pw.close();

			}

		} catch (Exception e) {
			FacadeGenUtil.messageStackTrace(messager, e);

		}

	}
}
